package com.tanhua.server.service;


//专门用来处理 tanhua-app-server中涉及到业务

import com.alibaba.fastjson.JSON;
import com.tanhua.autoconfig.templates.AipFaceTemplate;
import com.tanhua.autoconfig.templates.HuanXinTemplate;
import com.tanhua.autoconfig.templates.OssTemplate;
import com.tanhua.autoconfig.templates.SmsTemplate;
import com.tanhua.domain.db.User;
import com.tanhua.domain.db.UserFreeze;
import com.tanhua.domain.db.UserInfo;
import com.tanhua.domain.mongo.Friend;
import com.tanhua.domain.mongo.UserLike;
import com.tanhua.domain.mongo.Visitors;
import com.tanhua.dubbo.api.db.UserApi;
import com.tanhua.dubbo.api.db.UserFreezeApi;
import com.tanhua.dubbo.api.db.UserInfoApi;
import com.tanhua.dubbo.api.mongo.FriendApi;
import com.tanhua.dubbo.api.mongo.RecommendUserApi;
import com.tanhua.dubbo.api.mongo.UserLikeApi;
import com.tanhua.server.exceptions.TanhuaErrorEnums;
import com.tanhua.server.exceptions.TanhuaException;
import com.tanhua.server.interceptors.UserHolder;
import com.tanhua.server.utils.JwtUtils;
import com.tanhua.vo.CountsVo;
import com.tanhua.vo.PageResult;
import com.tanhua.vo.UserInfoVo;
import com.tanhua.vo.UserLikeVo;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.checkerframework.checker.units.qual.C;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;
import java.util.concurrent.TimeUnit;

@Service  // spring的@Service注解
public class UserService {


    @Reference // dubbo的注解
    private UserApi userApi;
    @Reference // dubbo的注解
    private UserInfoApi userInfoApi;
    @Reference
    private UserFreezeApi userFreezeApi;//冻结

    @Autowired
    private SmsTemplate smsTemplate;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private HuanXinTemplate huanXinTemplate;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    //更改手机号——验证验证码
    public ResponseEntity checkCode(String code) {
        String mobile = UserHolder.getUser().getMobile();
        //获取redis中存入的验证码
        //第一步：从redis中获取刚才发送的验证码，但是可能获取不到 可能超时
        String code1 = redisTemplate.boundValueOps(PRIFIX + mobile).get();
        boolean bool = true;
        if (code == null) {
            //抛异常
            throw new TanhuaException(TanhuaErrorEnums.CODEFAIL);
        }
        //第二步：判断验证码是否正确

        if (!code.equals(code)) {
            //验证码不一致  抛异常
            bool = false;
        }
        redisTemplate.delete(PRIFIX + mobile);
        //3、构造返回值
        Map<String, Object> result = new HashMap<>();
        result.put("verification", bool);
        return ResponseEntity.ok(result);
    }

    //保存新手机号
    public ResponseEntity saveNewMobile(String mobile) {
        //获取当前操作用户
        User user = UserHolder.getUser();
        //判断新手机号是否已经注册
        User exist = userApi.findByMobile(mobile);
        if(exist != null) {
            new TanhuaException(TanhuaErrorEnums.valueOf("手机号已经存在"));
            //return ResponseEntity.status(500).body(ErrorResult.mobileError());
            //或者抛个异常
        }
        //绑定更新
        user.setMobile(mobile);
        userApi.update(user);
        return ResponseEntity.ok(null);

    }

    public ResponseEntity findByMobile(String mobile) {
        User user  = userApi.findByMobile(mobile);
        return ResponseEntity.status(2000).body(user);
    }

    public ResponseEntity saveUser(String mobile, String password) {
        User user = new User();
        user.setPassword(DigestUtils.md5Hex(password)); // 密码md5加密
        user.setMobile(mobile);

        Long userId = userApi.save(user);
//        return ResponseEntity.status(3000).body(userId);
        return ResponseEntity.ok(userId);  //ok 返回的状态码是200
    }

    private String PRIFIX = "tanhua_code_";

    public ResponseEntity sendCode(String phone){
//        1、借助阿里云发送短信
        //        随机生成6位的数字
//        String randomNumeric = RandomStringUtils.randomNumeric(6);
        String randomNumeric = "123456";
        try {
//            smsTemplate.sendSms(phone,randomNumeric);  // TODO 为了省钱，因为后面基本上每天都会发好多条短信
        } catch (Exception e) {
            throw new TanhuaException(TanhuaErrorEnums.CODEFAIL);
        }
//        2、为了跟用户输入的验证码比较，所以还需要把验证码存到redis中，并且设置超时时间5分钟
        redisTemplate.boundValueOps(PRIFIX+phone).set(randomNumeric,5, TimeUnit.MINUTES); //设置超时时间
        System.out.println("发送的验证码"+randomNumeric);

        return ResponseEntity.ok(null); //不返回任何结果
    }
//    请求的参数在body中：{"phone":"13800138000","verificationCode":"123456"}
//    返回的数据json：{"token":"qegshreerscbcc","isNew":true}
    public ResponseEntity loginVerification(String phone, String verificationCode) {
//       第一步： 从redis中获取刚才发送的验证码，但是有可能获取不到（因为超时了）
        String code = redisTemplate.boundValueOps(PRIFIX + phone).get();
        if(code==null){
//            throw new RuntimeException("验证码失效");  //默认的状态码就是500  我想自定义状态码  不要一出现问题就是500这样的状态码
            throw new TanhuaException(TanhuaErrorEnums.CODETIMEOUTERROR); //  //默认的状态码就是500  我想自定义状态码  不要一出现问题就是500这样的状态码
        }
//       第二步：判断验证码是否正确
        if(!code.equals(verificationCode)){
//            意味着两个验证码不一样
            throw new TanhuaException(TanhuaErrorEnums.CODELOGINERROR);
        }
//        第三步：根据手机号从数据库中查询，判断是否为新用户
        User user = userApi.findByMobile(phone);
        Long userId = null;
        Boolean isNew = false;

        if(user==null){
            isNew = true;
//            意味着这是一个新用户
//            第四步：如果是新用户，把新用户的数据插入到tb_user表中
            user = new User();
            user.setMobile(phone);
            user.setPassword(DigestUtils.md5Hex("123456")); //象征性的给设置一个密码
            userId = userApi.save(user);
            user.setId(userId);  //注意这个位置

//            还需要把用户注册到环信中
            huanXinTemplate.register(userId);
        }else{
            userId = user.getId();
            //添加冻结查询tb_user_userfreeze表
          UserFreeze userFreeze= userFreezeApi.findById(userId);
            if (userFreeze!=null) {
                Integer freezingRange = userFreeze.getFreezingRange();
                if (freezingRange==1){

                   System.out.println("该用户已冻结");
                   return ResponseEntity.ok(null);

                }
            }


        }

//      第五步：把用户信息加密成token字符串存储到redis中
        String token = JwtUtils.createToken(phone, userId, "tanhua");

//        把token放入到redis中是为了什么？ 为了app携带token时能判断出这个人是谁
        String userJson = JSON.toJSONString(user); //把用户对象转成json字符串
        redisTemplate.boundValueOps("TOKEN_"+token).set(userJson,2,TimeUnit.HOURS);
//        第六步：清除redis中的这个验证码
        redisTemplate.delete(PRIFIX + phone);


        Map resultMap = new HashMap<>(); // 返回的结果
//    返回的数据json：{"token":"qegshreerscbcc","isNew":true}
        resultMap.put("token",token);
        resultMap.put("isNew",isNew);


        //向mq中放消息
//        userId type logTime
        Map mqMap = new HashMap();
        mqMap.put("userId",userId);
        mqMap.put("type",isNew?"0102":"0101"); //0101为登录，0102为注册
        mqMap.put("logTime",new DateTime().toString("yyyy-MM-dd"));
        rocketMQTemplate.convertAndSend("tanhua-logs",mqMap);
        System.out.println("消息发送成功，，，"+mqMap);

        return  ResponseEntity.ok(resultMap) ;

    }

//    完善用户信息,就是向tb_user_info表中插入数据
    public ResponseEntity loginReginfo(UserInfo userInfo, String token) {
//        userInfo里面是没有ID值的  需要根据token从redis中获取user信息
        User user = getUserByToken(token);
        userInfo.setId(user.getId()); //这个id不是主键自增的  是用user对象中获取的
        userInfoApi.save(userInfo);
        return ResponseEntity.ok(null);
    }

    public User getUserByToken(String token) {
        String userJson = redisTemplate.boundValueOps("TOKEN_" + token).get();
//        把json字符串转成user对象
        if(userJson==null){
            return null;
        }
//        不停地给token续签
        redisTemplate.boundValueOps("TOKEN_"+token).set(userJson,2,TimeUnit.HOURS);
        return JSON.parseObject(userJson, User.class);
    }


    @Autowired
    private AipFaceTemplate aipFaceTemplate;
    @Autowired
    private OssTemplate ossTemplate;

//    上传头像，本质上就是想tb_user_info表中的设置 avatar的值
    public ResponseEntity loginReginfoHead(MultipartFile headPhoto) throws Exception {
//        1、人脸识别
        boolean isHumanFace = aipFaceTemplate.detect(headPhoto.getBytes());
        if(!isHumanFace){
            throw new TanhuaException(TanhuaErrorEnums.FACEERROR);
        }
//        2、如果是人脸才会上传到阿里云 返回一个url
        String avatarUrl = ossTemplate.upload(headPhoto.getOriginalFilename(), headPhoto.getInputStream());

        User user = UserHolder.getUser();
//        3、更新表中的avatar的值 //        update tb_user_info set avatar=?? where id=????
        UserInfo userInfo = new UserInfo();
        userInfo.setId(user.getId());
        userInfo.setAvatar(avatarUrl);
        userInfoApi.update(userInfo);
        return ResponseEntity.ok(null);

    }

    public ResponseEntity queryUserInfoById(Long uid) {

        UserInfo userInfo = userInfoApi.findById(uid);

        UserInfoVo userInfoVo = new UserInfoVo();

//        Object source, Object target  复制的是属性名称并且数据类型一致的
        BeanUtils.copyProperties(userInfo,userInfoVo);
        userInfoVo.setAge(userInfo.getAge()+"");

        return ResponseEntity.ok(userInfoVo);

    }

    public ResponseEntity updateUserInfo(UserInfo userInfo) {
        User user = UserHolder.getUser();
//        设置修改的UserInfo的id值
        userInfo.setId(user.getId());
        userInfoApi.update(userInfo);
        return ResponseEntity.ok(null);
    }

    @Reference
    private UserLikeApi userLikeApi;

    public ResponseEntity queryCounts() {
        CountsVo countsVo = new CountsVo();

        Long userId = UserHolder.getUserId();

//        相互喜欢
        Long eachLoveCount  = userLikeApi.queryEachLoveCount(userId);
        countsVo.setEachLoveCount(eachLoveCount);
//        我的粉丝
        Long fanCount  = userLikeApi.queryFanCount(userId);
        countsVo.setFanCount(fanCount);
//        我的喜欢
        Long loveCount  = userLikeApi.queryLoveCount(userId);
        countsVo.setLoveCount(loveCount);

        return ResponseEntity.ok(countsVo);

    }

    @Reference
    private RecommendUserApi recommendUserApi;
//1 互相喜欢
//2 我喜欢
//3 粉丝
//4 谁看过我
    public ResponseEntity queryUserLikeList(Integer type, Integer page, Integer pagesize) {

        PageResult pageResult = new PageResult(page,pagesize,0,new ArrayList());

        Long userId = UserHolder.getUserId();

        UserLikeVo userLikeVo = null;
        List<UserLikeVo> userLikeVoList = new ArrayList<>();
        switch (type){
            case 1:{
                pageResult = userLikeApi.queryEachLoveList(page,pagesize,userId);
                List<Friend> items = (List<Friend>) pageResult.getItems();
                for (Friend item : items) {
                    UserInfo userInfo = userInfoApi.findById(item.getFriendId());
                    if(userInfo==null){
                        continue;
                    }
                    userLikeVo = new UserLikeVo();
                    BeanUtils.copyProperties(userInfo,userLikeVo);
                    Long score = recommendUserApi.queryScore(userId,userInfo.getId());
                    userLikeVo.setMatchRate(score.intValue());
                    userLikeVoList.add(userLikeVo);
                }
                break;
            }
            case 2:{
                //2 我喜欢的人
                pageResult =  userLikeApi.queryLoveList(page,pagesize,userId);

                List<UserLike> items = (List<UserLike>) pageResult.getItems();
                for (UserLike item : items) {
                    UserInfo userInfo = userInfoApi.findById(item.getLikeUserId());
                    if(userInfo==null){
                        continue;
                    }
                    userLikeVo = new UserLikeVo();
                    BeanUtils.copyProperties(userInfo,userLikeVo);
                    Long score = recommendUserApi.queryScore(userId,userInfo.getId());
                    userLikeVo.setMatchRate(score.intValue());
                    userLikeVoList.add(userLikeVo);
                }

                break;
            }
            case 3:{
                pageResult =  userLikeApi.queryFansList(page,pagesize,userId);
                List<UserLike> items = (List<UserLike>) pageResult.getItems();
                for (UserLike item : items) {
                    UserInfo userInfo = userInfoApi.findById(item.getUserId());
                    if(userInfo==null){
                        continue;
                    }
                    userLikeVo = new UserLikeVo();
                    BeanUtils.copyProperties(userInfo,userLikeVo);
                    Long score = recommendUserApi.queryScore(userId,userInfo.getId());
                    userLikeVo.setMatchRate(score.intValue());
                    userLikeVoList.add(userLikeVo);
                }
                break;
            }
            case 4:{
//                访问记录
                pageResult =  userLikeApi.queryVisitorsList(page,pagesize,userId);
                List<Visitors> items = (List<Visitors>) pageResult.getItems();
                for (Visitors item : items) {
                    UserInfo userInfo = userInfoApi.findById(item.getVisitorUserId());
                    if(userInfo==null){
                        continue;
                    }
                    userLikeVo = new UserLikeVo();
                    BeanUtils.copyProperties(userInfo,userLikeVo);
                    Long score = recommendUserApi.queryScore(userId,userInfo.getId());
                    userLikeVo.setMatchRate(score.intValue());
                    userLikeVoList.add(userLikeVo);
                }
                break;
            }
        }
        pageResult.setItems(userLikeVoList);
        return ResponseEntity.ok(pageResult);
    }

    @Reference
    private FriendApi friendApi;

//    对粉丝喜欢
    public ResponseEntity likeFans(Long fansUserId) {
        Long userId = UserHolder.getUserId();
//       1、成为好友
        friendApi.save(userId,fansUserId);
//       2、注册到环信上
//        huanXinTemplate.contactUsers(userId,fansUserId); //暂时在开发时先忽略
//       3、删除粉丝关系  举例 1号用户要删除的粉丝是58号用户  userId =1   fansUserId=58
        userLikeApi.delete(fansUserId,userId);  //即可以删除粉丝关系 也可以删除喜欢关系
        return ResponseEntity.ok(null);
    }

//    取消喜欢
    public ResponseEntity deleteFans(Long friendId) {
//        1、判断 取消喜欢是从 【互相喜欢】发出还是从【喜欢】发出 判断的依据就是查看是否有好友关系
        Long userId = UserHolder.getUserId();
        Friend friend = friendApi.findOne(userId,friendId);
        if(friend==null){
//            从【喜欢】发出  当前登录人是1号用户  删除的是57号好友
            userLikeApi.delete(userId,friendId);
        }else{
//            当前登录人是1号用户  解除的是57号用户   57号就不是我的好友了变成了我的粉丝
//            解除好友关系
            friendApi.delete(userId,friendId);
//          变成粉丝关系
            userLikeApi.save(friendId,userId);// 57号喜欢1号    likeUserId的位置是1 userId的位置是57
        }

        return ResponseEntity.ok(null);
    }
}
